package com.ruoyi.riskrule.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.mapper.ApplyContactsMapper;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.constant.RiskConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.MyBeanUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.extdata.common.config.RuleConfig;
import com.ruoyi.riskrule.config.common.RuleUtils;
import com.ruoyi.riskrule.config.step1.DerivedParamsLoader;
import com.ruoyi.riskrule.config.step1.OriginalParamsLoader;
import com.ruoyi.riskrule.constants.Constants;
import com.ruoyi.riskrule.domain.RuleCreditDto;
import com.ruoyi.riskrule.domain.RuleInCustomerData;
import com.ruoyi.riskrule.mapper.CustomerCreditReportMapper;
import com.ruoyi.riskrule.service.ICreditFieldService;
import com.ruoyi.riskrule.service.ICustomerCreditService;
import com.ruoyi.riskrule.service.IRiskCustomerService;
import com.ruoyi.riskrule.service.ILoanFieldService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@Configuration
@AllArgsConstructor
public class Step1ParamsLoader {

    private RuleConfig ruleConfig;

    private ILoanOrderService loanOrderService;

    private ILoanIouService iLoanIouService;

    private ISysDictDataService sysDictDataService;

    private ICreditApplyService creditApplyService;

    private IRealNameAuthService realNameAuthService;

    private IRiskAppListService riskAppListService;

    private IAppDeviceInfoService appDeviceInfoService;

    private ICreditFieldService creditService;

    private IAppUserService appUserService;

    private ICreditAccountService creditAccountService;

    private ILoanFieldService loanService;

    private ICreditFlagService creditFlagService;

    private ICustomerXdsReportService icustomerXdsReportService;

    private ICustBankCardService iCustBankCardService;

    private CustomerCreditReportMapper customerCreditReportMapper;

    private ICustomerCreditService customerCreditService;

    private IRiskCustomerService customerService;

    private IApplyAppListService iApplyAppListService;

    private IDeviceAppListService iDeviceAppListService;

    private IApplyAppDataService iApplyAppDataService;

    private IApplyContactsService iApplyContactsService;

    private ICustomerInfoService customerInfoService;

    private IDeviceContactsService iDeviceContactsService;

    private IDeviceContactsRelativeService iDeviceContactsRelativeService;

    private ApplyContactsMapper applyContactsMapper;

    private ICustReplenishInfoService replenishInfoService;

    private ISmsAreaNumberConfigService iSmsAreaNumberConfigService;

    private DerivedParamsLoader derivedParamsLoader;

    private BindCardParamsLoader bindCardParamsLoader;

    private IRuleInNextStepService iRuleInNextStepService;

    private IBankAccountService bankAccountService;

    private ICustBankCardService custBankCardService;

    private ILoanIouDeferredService loanIouDeferredService;

    private IProductDeferredInfoService productDeferredInfoService;


    //规则参数加工
    public RuleIn initRuleInParam(String type, String typeKey) {
        log.info("规则参数加工 initRuleInParam，type：{}, typeKey：{}");

        RuleIn ruleIn = new RuleIn();
        ruleIn.setEntryId(IdUtils.reqId());
        ruleIn.setProductCode(ruleConfig.getProductCode());
        ruleIn.setRunType(ruleConfig.getRunType());

        //CreditApply apply = new CreditApply();
        LoanOrder loanOrder = null;
        AppDeviceInfo appDeviceInfo = new AppDeviceInfo();

        //设备授权信息用的流水号
        CreditFlag creditFlag = new CreditFlag();
        creditFlag.setSerialNo(typeKey);
        creditFlag.setType(type);
        List<CreditFlag> creditFlags = creditFlagService.selectCreditFlagList(creditFlag);
        String contactsRelationNo = creditFlags.get(0).getContactsRelationNo();
        String appRelationNo = creditFlags.get(0).getAppRelationNo();
        Date applyTime = creditFlags.get(0).getCreateTime();
        //String relationNo = creditFlags.get(0).getRelationNo();

        if (StringUtils.isBlank(contactsRelationNo) || StringUtils.isBlank(appRelationNo)) {
            throw new BusinessException(RspEnmu.FLAG_NOT_EXIST);
        }

        String custNo = creditFlags.get(0).getCustNo();

        //填充deviceInfo数据
        appDeviceInfo.setActionKey(typeKey);
        appDeviceInfo.setState(UserConstants.NORMAL);
        List<AppDeviceInfo> AppDeviceInfoList = appDeviceInfoService.selectAppDeviceInfoList(appDeviceInfo);
        appDeviceInfo = AppDeviceInfoList.get(0);
        OriginalParamsLoader.setRuleInByDeviceInfo(ruleIn, appDeviceInfo);
        derivedParamsLoader.setRuleInByDeviceInfoDerived(ruleIn, appDeviceInfo);

        String userId = appDeviceInfo.getUserId();

        //填充creditApply数据
        CreditApply creditApply = getCreditApply(type, typeKey, custNo);
        ruleIn.setApplyHour(creditApply.getCreateTime().getHours() + "");
        ruleIn.setApplySucessHour(creditApply.getCreateTime().getHours() + "");
        ruleIn.setCustNo(userId);
        ruleIn.setApplySerialNo(creditApply.getApplySerialNo());

        QueryWrapper<RuleInNextStep> ruleInNextStepQueryWrapper = new QueryWrapper<>();
        ruleInNextStepQueryWrapper.eq("apply_serial_no", creditApply.getApplySerialNo());
        ruleInNextStepQueryWrapper.eq("oper_type", "3").last("limit 1");
        RuleInNextStep one = iRuleInNextStepService.getOne(ruleInNextStepQueryWrapper);
        if (one != null) {
            ruleIn.setReporttype(one.getReporttype());
        }
        //填充custInfo数据
        RuleInCustomerData ruleInCustomerData = buildCustmoerData(type, typeKey, creditApply);
        OriginalParamsLoader.setRuleInByCustomerData(ruleIn, ruleInCustomerData);
        derivedParamsLoader.setRuleInByCustomerDataDerived(ruleIn);

        //获取所有逾期客户的实名号码和注册号码
        List<Map<String, String>> overduePhones = creditService.getOverdueRealNames();
        //获取运营商对应关系
        List<SmsAreaNumberConfig> smsAreaNumberConfigs = iSmsAreaNumberConfigService.selectSmsAreaNumberConfigList(new SmsAreaNumberConfig());

        //填充appUser数据
        AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().eq("user_uuid", userId).last("limit 1"));
        OriginalParamsLoader.setRuleInByAppUser(ruleIn, appUser, overduePhones, smsAreaNumberConfigs);
        derivedParamsLoader.setRuleInByAppUserDerived(ruleIn, appUser);


        //1授信2提现
        if (RiskConstants.RULE_TYPE_APPLY.equals(type)) {
            ruleIn.setOperType("1");
            ruleIn.setWorkflowCode(RuleConfig.RULE_WORK_FLOW_CODE_CREDIT);
            AppDeviceInfo appDeviceInfo1 = appDeviceInfoService.getOne(new QueryWrapper<AppDeviceInfo>().eq("cust_no", appDeviceInfo.getCustNo()).eq("state", 0).eq("action_type", "apply").last("order by create_time desc limit 1"));
            ruleIn.setNewfingerprint(StringUtils.isNotNull(appDeviceInfo1) == true ? appDeviceInfo1.getNewFingerprint() : "-1");
            log.info("新的指纹:", appDeviceInfo1);
            //申请信息查询条件
            ruleIn.setApplySerialNo(typeKey);
        } else if (RiskConstants.RULE_TYPE_LOAN.equals(type)) {
            ruleIn.setOperType("2");
            ruleIn.setWorkflowCode(RuleConfig.RULE_WORK_FLOW_CODE_LOAN);
            //新的指纹
            AppDeviceInfo appDeviceInfo1 = appDeviceInfoService.getOne(new QueryWrapper<AppDeviceInfo>().eq("cust_no", appDeviceInfo.getCustNo()).eq("state", 0).eq("action_type", "loan").last("order by create_time desc limit 1"));
            ruleIn.setNewfingerprint(StringUtils.isNotNull(appDeviceInfo1) == true ? appDeviceInfo1.getNewFingerprint() : "-1");
            log.info("新的指纹:", appDeviceInfo1);
            //客户申请延期总次数
            List<LoanIou> iouList = iLoanIouService.getListByCustNo(custNo);

            int count = loanIouDeferredService.count(new QueryWrapper<LoanIouDeferred>().eq("cust_no", custNo));
            ruleIn.setDeferredcnt(count == 0 ? "-1" : count + "");

            log.info("custnomber:{}", appDeviceInfo.getCustNo());

            //当前客户申请延期的合同数
            Integer deferredhetong = getDeferredHeTong(appDeviceInfo.getCustNo());
            ruleIn.setDeferredhetong(deferredhetong == 0 ? "-1" : deferredhetong + "");
            log.info("deferredhetong为:{}", deferredhetong);

            //当前客户总延期天数
            int deferredTotalDay = loanIouDeferredService.getDeferredTotalDay(appDeviceInfo.getCustNo());
            ruleIn.setDeferredtotalday(deferredTotalDay == 0 ? "-1" : deferredTotalDay + "");
            log.info("deferredTotalDay:{}", deferredTotalDay);

            //当前提现距该客户最近一次提现成功的时间
            String whdwsjcha2 = getwhdwsjcha2(appDeviceInfo.getCustNo());
            ruleIn.setWhdwsjcha2(whdwsjcha2);
            //提现借据信息
            ruleIn.setLoanSerialNo(typeKey);
            loanOrder = new LoanOrder();
            loanOrder.setLoanSerialNo(typeKey);
            loanOrder.setState(UserConstants.BUSINESS_NORMAL);
            List<LoanOrder> loanOrderList = loanOrderService.selectLoanOrderList(loanOrder);
            if (CollectionUtils.isEmpty(loanOrderList)) {
                throw new BusinessException(RspEnmu.NO_RECORD);
            }
            loanOrder = loanOrderList.get(0);

            String loanTypeKey = loanOrder.getLoanPurpose();
            String loanTypeLable = sysDictDataService.selectDictLabel("loan_purpose", loanTypeKey);
            ruleIn.setLoanUsed(loanTypeLable);
            ruleIn.setCardNo(loanOrder.getAccountNumber());

            //当前申请提现金额
            ruleIn.setCurrentApplyLine(loanOrder.getLoanAmt() == null ? "0" : loanOrder.getLoanAmt().toString());
            //当前申请提现选择产品的天数
            ruleIn.setCurrentApplyPeriod(loanOrder.getPeriodNum() + "");

            //min_duedate
            LoanIou loanIou = new LoanIou();
            loanIou.setCustNo(loanOrder.getCustNo());
            loanIou.setState(Constants.BIZ_STATUS_1);
            loanIou.setIouStatus(0);
            //当前客户所有未结清合同的最近到期日
            String minDuedate = iLoanIouService.selectMinDueData(loanOrder.getCustNo());
            String replace = "";
            if (minDuedate.contains("/")) {
                replace = minDuedate.replace("/", "-");
                replace = replace + " 00:00:00";
                ruleIn.setMinDuedate(replace);
            } else {
                ruleIn.setMinDuedate(minDuedate);
            }
//            List<LoanIou> loanIouList = iLoanIouService.selectLoanIouList(loanIou);
//            if (loanIouList.size() > 0) {
//                Collections.sort(loanIouList, Comparator.comparing(o -> DateUtils.parseDate(o.getRepayDate())));
//                //Collections.sort(loanIouList, Comparator.comparing(BaseEntity::getCreateTime));
//                ruleIn.setMinDuedate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", DateUtils.parseDate(loanIouList.get(0).getRepayDate())));
//            }


            RealNameAuth auth = new RealNameAuth();
            auth.setCustNo(loanOrder.getCustNo());
            auth.setState(Constants.BIZ_STATUS_1);
            List<RealNameAuth> realNameAuthList = realNameAuthService.selectRealNameAuthList(auth);
            if (realNameAuthList.size() == 0) {
                throw new BusinessException(RspEnmu.USERID_IS_EMPTY);
            }
            RealNameAuth realName = realNameAuthList.get(0);

            CustomerXdsReport customerXdsReport = new CustomerXdsReport();
            customerXdsReport.setUserId(realName.getUserId());
            customerXdsReport.setStatus(UserConstants.BUSINESS_NORMAL);
            //
            List<CustomerXdsReport> customerXdsReports = icustomerXdsReportService.selectCustomerXdsReportList(customerXdsReport);

            log.debug("customerXdsReports.size===" + customerXdsReports.size());
            if (customerXdsReports.size() > 0) {
                Collections.sort(customerXdsReports, Comparator.comparing(o -> o.getCreateTime()));
                ruleIn.setXdschecked("1");
                ruleIn.setLasttimexds(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", customerXdsReports.get(customerXdsReports.size() - 1).getCreateTime()));
            } else {
                ruleIn.setXdschecked("0");
                ruleIn.setLasttimexds(Constants.DEFAULT_TIME);
            }

            //征信有效期
            String expiryDate = customerService.getExpiryDateByUserId(realName.getUserId());
            ruleIn.setExpiryDate(expiryDate);
            //老用户补充有效期
            if (Func.isEmpty(expiryDate)) {
                ruleIn.setExpiryDate("0");
                RuleCreditDto ruleCreditDto = customerCreditService.creditCheck(realName.getUserId(), realName.getBvnAccount());
                //近一次查得时间距离当前时间<=30天；征信有效期统一为30
                if (ruleCreditDto.getCreateTime() != null && Func.dayDifference(ruleCreditDto.getCreateTime()) <= 30) {
                    ruleIn.setExpiryDate("30");
                }
            }
            CustomerInfo customerInfo = new CustomerInfo();
            customerInfo.setExpiryDate(ruleIn.getExpiryDate());
            customerInfo.setUserId(realName.getUserId());
            customerService.updateExpiryDate(customerInfo);


            //发薪日与账单日差
            if (StringUtils.isNotBlank(ruleIn.getSalarydate())) {
                String salaryDayStr = Pattern.compile("[^0-9]").matcher(ruleIn.getSalarydate()).replaceAll("").trim();
                if (StringUtils.isNotBlank(salaryDayStr)) {
                    int repayDay = Integer.parseInt(DateUtils.parseDateToStr("dd", DateUtils.parseDate(loanOrder.getRepayDate())));
                    int salaryDay = Integer.parseInt(salaryDayStr);
                    if (repayDay == salaryDay) {
                        ruleIn.setDiffpayandbill("0");
                    } else if (repayDay > salaryDay) {
                        ruleIn.setDiffpayandbill((salaryDay - repayDay + 31) + "");
                    } else if (repayDay < salaryDay) {
                        ruleIn.setDiffpayandbill((salaryDay - repayDay) + "");
                    }
                }
            }

        } else if (RiskConstants.RULE_TYPE_REPLENISH.equals(type)) {

        } else {
            throw new BusinessException(RspEnmu.NO_RECORD);
        }

        QueryWrapper<ApplyAppList> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("apply_no", appRelationNo).last("order by id desc limit 1");
        ApplyAppList applyAppList = iApplyAppListService.getOne(objectQueryWrapper);

        String appIds = "";

        String deviceIdByUserId = appDeviceInfoService.getDeviceIdByActionKey(typeKey);

        //获取APP总数
        int appCount = 0;
        if (applyAppList != null) {
            appCount = applyAppList.getAppIds().split(",").length;
            appIds = applyAppList.getAppIds();
        } else {
            QueryWrapper<DeviceAppList> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("apply_no", appRelationNo).last("order by id desc limit 1");
            DeviceAppList deviceAppList = iDeviceAppListService.getOne(queryWrapper);
            appCount = deviceAppList.getAppIds().split(",").length;
            appIds = deviceAppList.getAppIds();
        }

        if (appCount > 0) {
            ruleIn.setDeviceAppNum(appCount + "");
        }


        //实名认证
        RealNameAuth auth = new RealNameAuth();
        auth.setUserId(userId);
        auth.setState(Constants.BIZ_STATUS_1);
        List<RealNameAuth> realNameAuthList = realNameAuthService.selectRealNameAuthList(auth);
        if (realNameAuthList.size() == 0) {
            throw new BusinessException(RspEnmu.USERID_IS_EMPTY);
        }
        RealNameAuth realName = realNameAuthList.get(0);
        OriginalParamsLoader.setRuleInByRealName(ruleIn, realName, smsAreaNumberConfigs);
        derivedParamsLoader.setRuleInByRealNameDerived(ruleIn, realName);

        String tableName = iApplyContactsService.getTableName(userId);
        List<DeviceContactsRelative> tableNames = iDeviceContactsRelativeService.getTableNamesByUserId(userId);
        applyContactsMapper.updateGroupConcatMaxLen();

        List<Integer> ids = new ArrayList<>();

        if (applyAppList != null && !"".equals(applyAppList.getAppIds())) {
            ids = iApplyAppListService.getIdsByCustNo(userId);
        } else {
            ids = iDeviceAppListService.getIdsByDeviceId(deviceIdByUserId);
        }

        //申请设备含坏信用关键字APP个数
        int deviceKeywordByBarCredit = iApplyAppDataService.deviceKeywordByBarCredit(ids);
        ruleIn.setBadCreditAppNum(deviceKeywordByBarCredit + "");
        //申请设备含贷款指引关键字APP个数
        int deviceKeywordByLoanGuideline = iApplyAppDataService.deviceKeywordByLoanGuideline(ids);
        ruleIn.setLoanTipGuideAppNum(deviceKeywordByLoanGuideline + "");

        //联系人手机号码是否匹配通讯录号码
        //int familycontact = creditService.familycontactInContact(userId, apply.getRelatePhone(), apply.getRelatePhone2());
        int familycontact = iApplyContactsService.familycontactInContact(tableName, tableNames, userId, ruleIn.getContactmobile(), ruleIn.getEmcontactnum());
        ruleIn.setFamilycontactInContact(familycontact + "");
        //获取用户当前申请单通讯录
        JSONArray contactsList = iApplyContactsService.getByCustNoAndApplyNo(userId, contactsRelationNo, tableName, tableNames);
        Set<String> phoneContacts = new HashSet<>();
        Set<String> callNameContacts = new HashSet<>();
        Set<JSONObject> phoneCallNameContacts = new HashSet<>();

        for (int i = 0; i < contactsList.size(); i++) {
            JSONObject jsonObject1 = contactsList.getJSONObject(i);
            phoneContacts.add(jsonObject1.getString("phone"));
            callNameContacts.add(jsonObject1.getString("callName"));
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("phone", jsonObject1.getString("phone"));
            jsonObject.put("callName", jsonObject1.getString("callName"));
            phoneCallNameContacts.add(jsonObject);
        }

        int ContactLikeBvn = 0;
        int ContactBVNCount = 0;
        int PersonalContactBVNCount = 0;
        Iterator<JSONObject> phoneCallNameContactsIterator = phoneCallNameContacts.iterator();

        while (phoneCallNameContactsIterator.hasNext()) {
            JSONObject res = phoneCallNameContactsIterator.next();

            String callName = res.getString("callName").toLowerCase();
            String phone = res.getString("phone").toLowerCase();
            if (callName.contains("bvn") || callName.contains("*565*0#") ||
                    phone.contains("bvn") || phone.contains("*565*0#") ||
                    DigitalExtraction(callName, null) || DigitalExtraction(phone, null)
            ) {
                ContactLikeBvn++;
            }
            if (DigitalExtraction(callName, null) ||
                    DigitalExtraction(phone, null)) {
                ContactBVNCount++;
            }
            if (DigitalExtraction(callName, realName.getBvnAccount()) ||
                    DigitalExtraction(phone, realName.getBvnAccount())) {
                PersonalContactBVNCount++;
            }
        }

        //当前申请单通讯录是否含有中文字符
        ruleIn.setContacthaschina("0");
        callNameContacts.forEach(e -> {
            if (Func.isContainChinese(e)) {
                ruleIn.setContacthaschina("1");
            }
        });

        //当前客户所有通讯录是否含有中文字符
        ruleIn.setAllcontacthaschina(iApplyContactsService.getAllcontacthaschina(tableNames, tableName, userId));

        //客户通讯录与BVN相关的通讯录条数
        ruleIn.setNumContactLikeBvn(ContactLikeBvn + "");
        //客户通讯录保存BVN通讯录条数
        ruleIn.setNumContactLikeBvnNumber(ContactBVNCount + "");
        //客户通讯录是否存有个人BVN
        ruleIn.setNumContactLikeBvnCust(PersonalContactBVNCount + "");

        //客户通讯录号码是否包含 逾期的用户 phone，bvn
        //Set<String> contactsSet = contactsList.stream().map(ApplyContacts::getPhone).collect(Collectors.toSet());
        int overdueNumInContacts = 0;

        //同一个客户 注册phone和实名phone 只命中一次
        for (Map<String, String> map : overduePhones) {
            String registNumber = StringUtils.substringAfter(map.get("registNumber"), 10);
            String realNamePhone = StringUtils.substringAfter(map.get("realNamePhone"), 10);
            for (String e : phoneContacts) {
                String phone = StringUtils.substringAfter(e, 10);
                if (StringUtils.equalsAny(phone, registNumber, realNamePhone)) {
                    overdueNumInContacts++;
                    break;
                }
            }
        }
        ruleIn.setOverdueNumInContacts(overdueNumInContacts + "");

        log.info("获取客户apps");
//        ApplyAppInfo applyAppInfo = new ApplyAppInfo();
//        applyAppInfo.setApplyNo(Func.isEmpty(relationNo) ? apply.getApplySerialNo() : relationNo);
//        List<ApplyAppInfo> appInfos = applyAppInfoService.selectApplyAppInfoList(applyAppInfo);

        List<String> appInfoList = iApplyAppDataService.getByIds(appIds);

        //Set<String> appInfoList = appInfos.stream().filter(res -> isEmpty(res.getPackageName())).map(ApplyAppInfo::getPackageName).collect(Collectors.toSet());
        List<RiskAppList> riskAppLists = riskAppListService.getAll();

        int appLoanNum = 0;
        int appBankNum = 0;
        int appLoanguideNum = 0;
        int appTransferNum = 0;
        for (String appInfoName : appInfoList) {
            boolean loanFlag = true;
            boolean bankFlag = true;
            boolean loanguideFlag = true;
            boolean transferFlag = true;
            for (RiskAppList riskAppList : riskAppLists) {
                //跳过不匹配的记录 不区分大小写
                if (!riskAppList.getAppId().toUpperCase().equals(appInfoName.toUpperCase())) {
                    continue;
                }
                //APPlist匹配贷款类APP个数
                if (riskAppList.getAppType().equals(Constants.Risk.LOAN) && loanFlag) {
                    appLoanNum++;
                    loanFlag = false;
                }
                //客户APPlist匹配银行类APP个数
                if (riskAppList.getAppType().equals(Constants.Risk.BANK) && bankFlag) {
                    appBankNum++;
                    bankFlag = false;
                }
                //客户APPlist匹配贷款指南类APP个数
                if (riskAppList.getAppType().equals(Constants.Risk.GUIDE) && loanguideFlag) {
                    appLoanguideNum++;
                    loanguideFlag = false;
                }
                //客户APPlist匹配钱包/支付/转账/收款类APP个数
                if (riskAppList.getAppType().equals(Constants.Risk.TRANSFER) && transferFlag) {
                    appTransferNum++;
                    transferFlag = false;
                }
            }
        }
        ruleIn.setAppLoanNum(appLoanNum + "");
        ruleIn.setAppBankNum(appBankNum + "");
        ruleIn.setAppLoanguideNum(appLoanguideNum + "");
        ruleIn.setAppTransferNum(appTransferNum + "");


        //客户通讯录名称匹配贷款类APP名称个数
        int ContactloanCategoryCount = 0;
        for (String contacts : callNameContacts) {
            for (RiskAppList riskAppList : riskAppLists) {
                if ("".equals(contacts)) {
                    continue;
                }
                boolean flag = riskAppList.getAppId().toUpperCase().contains(contacts.toUpperCase());
                if (riskAppList.getAppType().equals(Constants.Risk.LOAN) && flag) {
                    ContactloanCategoryCount++;
                    break;
                }
            }
        }
        ruleIn.setNumContactLikeLoanapp(ContactloanCategoryCount + "");

        Map<String, Integer> creditApplyNumsMap = creditService.getCreditApplyNums(userId);
        //当前申请人授信申请拒绝订单数
        ruleIn.setRejects(creditApplyNumsMap.get("rejects") + "");
        //当前申请人授信申请通过订单数
        ruleIn.setAccepts(creditApplyNumsMap.get("accepts") + "");
        //该客户发起授信申请次数
        ruleIn.setOrders(creditApplyNumsMap.get("count") + "");
        //客户最近一次经决策引擎的授信申请结果
        CreditApply recentResult = creditService.getApprovedRecentResult(userId);
        if (recentResult != null) {
            ruleIn.setRecentresults(0 == recentResult.getApplyStatus() ? "拒绝" : "成功");
        }

        //申请人逾期？
        ruleIn.setApplyOverdueFlag("0");
        if (StringUtils.isNotBlank(custNo) && RiskConstants.RULE_TYPE_LOAN.equals(type)) {
            CreditAccount creditAccount = new CreditAccount();
            creditAccount.setCustNo(custNo);
            creditAccount.setState(UserConstants.BUSINESS_NORMAL);
            List<CreditAccount> selectCreditAccountList = creditAccountService.selectCreditAccountList(creditAccount);

            if (!CollectionUtils.isEmpty(selectCreditAccountList)) {
                creditAccount = selectCreditAccountList.get(0);
                ruleIn.setCreditLine(creditAccount.getCreditLine().toString());
                if (UserConstants.BUSINESS_NOT_NORMAL.equals(creditAccount.getIsOverdue())) {
                    ruleIn.setApplyOverdueFlag(creditAccount.getIsOverdue());
                }
            }
        }

        //提现衍生字段
        if (RiskConstants.RULE_TYPE_LOAN.equals(type)) {

            LoanOrder approvedRecentResult = loanService.getApprovedRecentResult(custNo);
            if (approvedRecentResult != null) {
                Integer loanStatus = approvedRecentResult.getLoanStatus();
                String str = "";
                if (8 == loanStatus) {
                    str = "关闭";
                } else if (10 == loanStatus) {
                    str = "取消";
                } else if (0 == loanStatus) {
                    str = "拒绝";
                } else {
                    str = "通过";
                }
                ruleIn.setTradeResults(str);
            }

            Map<String, Integer> loanOrderNumsMap = loanService.getLoanOrderNums(custNo);

            ruleIn.setTradeRejects(loanOrderNumsMap.get("traderejects") + "");
            ruleIn.setTradeAccepts(loanOrderNumsMap.get("tradeaccepts") + "");
            ruleIn.setTradeOrders(loanOrderNumsMap.get("count") + "");


            //该客户所有提现成功的次数
            ruleIn.setWithdrawsucd(loanService.selectContractsByStatus(custNo, null, null) + "");
            Integer[] statusArr = new Integer[2];
            statusArr[0] = 1;
            //当前申请人结清合同数
            ruleIn.setJieqinghetong(loanService.selectContractsByStatus(custNo, statusArr, null) + "");//结清
            //当前申请人未结清合同数
            statusArr[0] = 0;
            statusArr[1] = 2;
            ruleIn.setZaidaihetong(loanService.selectContractsByStatus(custNo, statusArr, null) + "");//待还款

            //获取客户所有的借据
            List<LoanIou> activeLoanList = loanService.getLoanIouByCustNo(custNo, null);
            BigDecimal zaidaibenjin = new BigDecimal(0);
            BigDecimal jieqingbenjin = new BigDecimal(0);
            BigDecimal jieqinglixi = new BigDecimal(0);
            BigDecimal jieqingfuwufei = new BigDecimal(0);
            BigDecimal jieqingfaxi = new BigDecimal(0);
            BigDecimal zaidaibenjin2 = BigDecimal.ZERO;

            for (LoanIou loanIou : activeLoanList) {

                if (loanIou.getIouStatus() == 0 || loanIou.getIouStatus() == 2) {
                    zaidaibenjin2 = zaidaibenjin2.add(loanIou.getLoanPrincipal());
                    zaidaibenjin = zaidaibenjin.add(loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal()));
                }


                jieqingbenjin = jieqingbenjin.add(loanIou.getRepaidPrincipal());
                jieqinglixi = jieqinglixi.add(loanIou.getRepaidInterest());
                jieqingfuwufei = jieqingfuwufei.add(loanIou.getRepaidServiceFee());
                jieqingfaxi = jieqingfaxi.add(loanIou.getRepaidLateFee());
            }
            ruleIn.setRestofamt(bigDecimalToString(StringUtils.isBlank(ruleIn.getCreditLine()) ? BigDecimal.ZERO : new BigDecimal(ruleIn.getCreditLine()).subtract(zaidaibenjin2)));
            //在贷本金
            ruleIn.setZaidaibenjin(bigDecimalToString(zaidaibenjin));
            //当前申请人结清本金
            ruleIn.setJieqingbenjin(bigDecimalToString(jieqingbenjin));
            //当前申请人结清利息
            String jieQingLiXi = loanIouDeferredService.getJieQingLiXi(custNo);
            ruleIn.setJieqinglixi(jieQingLiXi);
//            ruleIn.setJieqinglixi(bigDecimalToString(jieqinglixi));
            //当前申请人结清服务费
            String jieQingFuWuFei = loanIouDeferredService.getJieQingFuWuFei(custNo);
            ruleIn.setJieqingfuwufei(jieQingFuWuFei);
//            ruleIn.setJieqingfuwufei(bigDecimalToString(jieqingfuwufei));
            //当前申请人结清罚息
            ruleIn.setJieqingfaxi(bigDecimalToString(jieqingfaxi));

            //该客户历史和当前的最大逾期天数
            Integer maximumOverdue = loanService.getMaximumOverdue(custNo);
            ruleIn.setMaxyuqitianshu((maximumOverdue == null ? 0 : maximumOverdue) + "");

            //该客户当前的最大逾期天数，可为0
            Integer currentOverdue = loanService.getCurrentOverdue(custNo);
            ruleIn.setCurrentmaxyuqi((currentOverdue == null ? 0 : currentOverdue) + "");

            //当前提现申请距该客户最近一次提现申请的时间
            Integer loanLastTimeInterval = loanService.getLastTimeInterval(custNo);
            ruleIn.setWhdwsjcha1(loanLastTimeInterval == null ? "0" : loanLastTimeInterval + "");
            //当前提现申请距该客户最近一次授信申请的时间
            Integer applyLastTimeInterval = creditService.getLastTimeInterval(loanOrder.getCustNo());
            ruleIn.setApplysjcha(applyLastTimeInterval == null ? "0" : applyLastTimeInterval + "");

            //当前提现申请距该客户最近的在贷账单日的时间，可为0
            Integer lastTimeIntervalOfIou = loanService.getLastTimeIntervalOfIou(loanOrder.getCustNo());
            String zdzhangdanricha = iLoanIouService.selectzdzhangdanricha(custNo);
            ruleIn.setZdzhangdanricha(zdzhangdanricha);
//            ruleIn.setZdzhangdanricha(lastTimeIntervalOfIou == null || lastTimeIntervalOfIou < 0 ? "-1" : lastTimeIntervalOfIou + "");
            //ruleIn.setZdzhangdanricha(Integer.parseInt(ruleIn.getZdzhangdanricha())<=0?"-1":ruleIn.getZdzhangdanricha());

            //申请人逾期？
            CreditAccount creditAccount = new CreditAccount();
            creditAccount.setCustNo(custNo);
            creditAccount.setState(UserConstants.BUSINESS_NORMAL);
            List<CreditAccount> selectCreditAccountList = creditAccountService.selectCreditAccountList(creditAccount);

            creditAccount = selectCreditAccountList.get(0);
            if ("1".equals(creditAccount.getOnLoan())) {
                ruleIn.setApplyOverdueFlag(creditAccount.getIsOverdue());
            }
            ruleIn.setCreditLine(creditAccount.getCreditLine().toString());


            LoanOrder loanOrderOne = loanService.getLoanOrderOne(typeKey);
            BigDecimal add = loanOrderOne.getLoanAmt().add(creditAccount.getLoanQuota());
            ruleIn.setCreditused(add.divide(creditAccount.getCreditLine(), BigDecimal.ROUND_HALF_UP) + "");

            // 当笔利息
            ruleIn.setCurrentinterest(loanOrderOne.getInterestAmt().toString());
            // 当笔服务费
            ruleIn.setCurrentservicefee(loanOrderOne.getServiceFee().toString());
            // 当笔罚息
            ruleIn.setCurrentlatefee(BigDecimal.ZERO.toString());

            // 代扣回款总额
            ruleIn.setWithholdamt(loanService.withholdingTotal(loanOrderOne.getCustNo()).toString());

            // 代扣结清数
            ruleIn.setWithholdnums(loanService.withholdingSettlementQuantity(loanOrderOne.getCustNo()));

        }

        //历史授信拒绝次数
        int cntCreditReject = creditService.getCntCreditReject(ruleIn.getCustNo());
        ruleIn.setCntCreditReject(cntCreditReject + "");

        //30天内授信拒绝次数
        int cntCreditFail = creditService.getCntCreditReject30(ruleIn.getCustNo());
        ruleIn.setCntCreditFail(cntCreditFail + "");

        //最近60天授信申请次数
        int cntCredit60Days = creditService.getCntCredit60Days(ruleIn.getCustNo());
        ruleIn.setCntCredit60Days(cntCredit60Days + "");

        //最近60天提现申请次数
        int cntApply60Days = creditService.getCntApply60Days(userId);
        ruleIn.setCntApply60Days(cntApply60Days + "");

        //历史提现拒绝次数
        int cntWithdrawReject = creditService.getCntWithdrawReject(userId);
        ruleIn.setCntWithdrawReject(cntWithdrawReject + "");

        //用户通讯录联系人数
        int cntContactsNum = 0;
        if (StringUtils.isNotBlank(tableName)) {
            cntContactsNum = iApplyContactsService.getCntContactsNum(tableName, userId, contactsRelationNo);
        } else {
            String tableNameByDeviceId = iDeviceContactsRelativeService.getTableNameByDeviceId(deviceIdByUserId);
            cntContactsNum = iDeviceContactsService.getCntContactsNum(tableNameByDeviceId, deviceIdByUserId, contactsRelationNo);
        }
        ruleIn.setCntContactsNum(cntContactsNum + "");

        //绑定的银行卡
        CustBankCard custBankCard = new CustBankCard();
        custBankCard.setState(UserConstants.BUSINESS_NORMAL);
        custBankCard.setCustNo(custNo);
        List<CustBankCard> custBankCards = iCustBankCardService.selectCustBankCardList(custBankCard);
        ruleIn.setBindcardno(custBankCards.size() + "");

        ruleIn.setCntDeviceTotal(creditService.getUseDistinctFingerprint(ruleIn.getCustNo()) + "");


        ruleIn.setState(UserConstants.BUSINESS_NORMAL);
        ruleIn.setRecFlag(UserConstants.BUSINESS_NOT_NORMAL);
        Date now = new Date();
        ruleIn.setCreateTime(now);
        ruleIn.setUpdateTime(now);

        if (StringUtils.isNotEmpty(userId)) {
            Date data = customerCreditReportMapper.getCustomerCreditReportData(userId);
            ruleIn.setLasttimereport(null != data ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(data) : Constants.DEFAULT_TIME);
        }


        //bvn关联用户数
        ruleIn.setBvnrelausermaxcnt(realNameAuthService.selectRealNameBvnTotal(realName.getCustNo()));
        //用户关联bvn数
        ruleIn.setBvncnt(String.valueOf(realNameAuthService.selectRealNameBvnCnt(realName.getCustNo())));
        //account关联用户数
        ruleIn.setAccountrelausermaxcnt(bankAccountService.selectBankAccountMaxCnt(realName.getCustNo()));
        //用户关联account数
        ruleIn.setAccountcnt(String.valueOf(bankAccountService.selectBankAccountCnt(realName.getCustNo())));
        //银行卡号关联用户数
        ruleIn.setCardrelausermaxcnt(custBankCardService.selectCustBankCardMaxCnt(realName.getCustNo()));
        //用户关联银行卡数
        ruleIn.setCardcnt(String.valueOf(custBankCardService.selectCustBankCardCnt(realName.getCustNo())));


        //已绑定有效银行卡数
        ruleIn.setCardineffectnum(bindCardParamsLoader.getCardineffectnum(realName.getCustNo()) + "");

        //风控要求 部分字段格式化
        return afterFormatRuleIn(ruleIn);
    }

    private String getwhdwsjcha2(String custNo) {
        return iLoanIouService.getwhdwsjcha2(custNo);
    }

    private int getDeferredHeTong(String custNo) {
        return iLoanIouService.getHaveDeIou(custNo);
    }

    private RuleInCustomerData buildCustmoerData(String type, String typeKey, CreditApply creditApply) {
        RuleInCustomerData customerData = new RuleInCustomerData();
        CustomerInfo customerInfo = customerInfoService.getOne(new QueryWrapper<CustomerInfo>().eq("cust_no", creditApply.getCustNo()));
        if (RiskConstants.RULE_TYPE_REPLENISH.equals(type)) {
            CustReplenishInfo replenishInfo = replenishInfoService.getOne(new QueryWrapper<CustReplenishInfo>().eq("serial_no", typeKey));

            log.info("补充信息字段日志1：{}", customerInfo.toString());
            MyBeanUtil.copyProperties(customerInfo, replenishInfo);
            log.info("补充信息字段日志2：{}", customerInfo.toString());
            BeanUtils.copyProperties(customerInfo, customerData);
            log.info("补充信息字段日志3：{}", customerData.toString());
            //如果customerInfo中的某些属性不为空，则用CustomerInfo的,否则使用客户提交的信息
            //customerData.customerAttributesTransfer(customerInfo);

        } else if (RiskConstants.RULE_TYPE_APPLY.equals(type)) {
            BeanUtils.copyProperties(creditApply, customerData);
        } else if (RiskConstants.RULE_TYPE_LOAN.equals(type)) {
            BeanUtils.copyProperties(customerInfo, customerData);
        }
        return customerData;
    }


    private CreditApply getCreditApply(String type, String typeKey, String custNo) {
        if (RiskConstants.RULE_TYPE_APPLY.equals(type)) {
            QueryWrapper<CreditApply> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("apply_serial_no", typeKey).eq("state", UserConstants.BUSINESS_NORMAL).last("limit 1");
            return creditApplyService.getOne(queryWrapper);
        } else if (RiskConstants.RULE_TYPE_LOAN.equals(type) || RiskConstants.RULE_TYPE_REPLENISH.equals(type)) {
            QueryWrapper<CreditApply> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("cust_no", custNo).eq("apply_status", BizConstants.APPLY_STATUS_1_PASSED).last("limit 1");
            return creditApplyService.getOne(queryWrapper);
        } else {
            throw new BusinessException(RspEnmu.NO_RECORD);
        }
    }

    private String bigDecimalToString(BigDecimal bigDecimal) {
        return bigDecimal == null ? "0.000" : bigDecimal + "";
    }

    private boolean DigitalExtraction(String str, String bvn) {
        String regEx = "[^0-9]";
        Pattern p = Pattern.compile(regEx);
        String trim = p.matcher(str).replaceAll("").trim();
        if (bvn != null) {
            return trim.startsWith("22") && trim.length() == 11 && trim.equals(bvn);
        }
        return trim.startsWith("22") && trim.length() == 11;
    }


    /**
     * field
     *
     * @param ruleIn
     * @return
     */
    public static RuleIn afterFormatRuleIn(RuleIn ruleIn) {

        ruleIn = RuleUtils.afterFormat(ruleIn);
        //去掉字母
        if (Func.isNotEmpty(ruleIn.getMaxstorage())) {
            ruleIn.setMaxstorage(ruleIn.getMaxstorage().replaceAll("[a-zA-Z]+", ""));
        }
        if (Func.isNotEmpty(ruleIn.getUsedstorage())) {
            String usedStorage = ruleIn.getUsedstorage().replaceAll("[a-zA-Z]+", "");
            usedStorage = usedStorage.replaceAll(",", ".");
            if (usedStorage.startsWith(".")) {
                usedStorage = "0" + usedStorage;
            }
            ruleIn.setUsedstorage(usedStorage);
        }
        //Android 7.1.1 -> 7
        if (Func.isNotEmpty(ruleIn.getAndroidno())) {
            ruleIn.setAndroidno(ruleIn.getAndroidno().replaceAll("[a-zA-Z]+", "").trim().split("\\.")[0]);
        }

        if (Constants.DEFAULT_VALUE.equals(ruleIn.getBvnRegisterTime())) {
            ruleIn.setBvnRegisterTime(Constants.DEFAULT_TIME);
        }

        if (Constants.DEFAULT_VALUE.equals(ruleIn.getMinDuedate())) {
            ruleIn.setMinDuedate(Constants.DEFAULT_TIME);
        }
        if (Constants.DEFAULT_VALUE.equals(ruleIn.getLasttimexds()) || StringUtils.isBlank(ruleIn.getLasttimexds())) {
            ruleIn.setLasttimexds(Constants.DEFAULT_TIME);
        }

        if (Constants.DEFAULT_VALUE.equals(ruleIn.getEntrytime())) {
            ruleIn.setEntrytime(Constants.DEFAULT_TIME);
        }
        return ruleIn;
    }


}
